#include "../src/distribution.c"
#include "../src/qfunc.c"

#include <assert.h>
#include <stdio.h>

typedef struct _QFuncTestDatum QFuncTestDatum;
struct _QFuncTestDatum
{ 
  struct
    {
      float    loga[6 * 4];
      float    logbeta;
      float    c[6 * 5];
      float    d[6 * 5];
      float    pz[5];
      Rating    ratings[8];
      float    logbetamean;
      float    logbetastddev;
    }                   inputs;

  struct
    {
      float     q;
      float     dlogbeta;
      float     ddlogbeta;
    }                   desired_output;
};

static void
test_qfunc (void)
{
  QFuncTestDatum data[] = 
    {{{{0.919679, 0.34311, 0.32444, 0.0585594, 0.538864, 0.389317,    0.665298, 0.884367, 0.434082, 0.790598, 0.433954, 0.214083,    0.999118, 0.089546, 0.919861, 0.657412, 0.623198, 0.232051,    0.642891, 0.631126, 0.60443, 0.810111, 0.107128, 0.557705},   0.684751, {0.467, 0.782688, 0.499145, 0.145887, 0.0776828, 0.11739,     0.614779, 0.711805, 0.287085, 0.683436, 0.400696, 0.712687,    0.197539, 0.763575, 0.743284, 0.0894885, 0.965488, 0.120684,    0.112158, 0.485058, 0.155377, 0.0135568, 0.554453, 0.800307,    0.688377, 0.230869, 0.0553079, 0.654419, 0.610694,    0.11348}, {0.440529, 0.942614, 0.323609, 0.430044, 0.0398335,    0.229927, 0.12607, 0.666468, 0.29655, 0.140439, 0.160582,    0.545784, 0.184392, 0.655381, 0.00520489, 0.532227, 0.629938,    0.855074, 0.316828, 0.301358, 0.57463, 0.200655, 0.706133,    0.187879, 0.134101, 0.25804, 0.382524, 0.757835, 0.0942676,    0.028113}, {0.256454, 0.0913665, 0.797718, 0.887674,    0.0958713}, {{3, 3}, {3, 0}, {3, 2}, {0, 3}, {2, 2}, {3, 2}, {0,     3}, {2, 4}}, 0.545582,   0.613326}, {-78.8647, -78.9953, -85.6519}}, {{{0.232294, 0.0906664,     0.0133552, 0.983388, 0.37722, 0.773839, 0.711997, 0.408758,    0.176565, 0.0677054, 0.524119, 0.274656, 0.918525, 0.685181,    0.766284, 0.180389, 0.890412, 0.428728, 0.674917, 0.382671,    0.00273767, 0.332857, 0.129335, 0.769344},   0.770444, {0.24219, 0.115979, 0.785956, 0.393224, 0.468351,    0.403982, 0.377199, 0.216659, 0.400646, 0.879864, 0.102542,    0.298134, 0.715465, 0.11358, 0.922153, 0.407723, 0.286737,    0.438663, 0.539483, 0.404985, 0.95388, 0.309328, 0.770138,    0.634541, 0.71169, 0.193349, 0.984182, 0.241316, 0.243338,    0.789367}, {0.606984, 0.0246572, 0.842692, 0.909503, 0.504441,    0.726523, 0.127228, 0.795923, 0.582288, 0.3188, 0.840491, 0.35726,     0.0428053, 0.913815, 0.886611, 0.0479313, 0.272667, 0.279274,    0.174921, 0.854582, 0.288485, 0.0379578, 0.931582, 0.0652156,    0.681501, 0.0133006, 0.0888901, 0.155713, 0.17706,    0.286778}, {0.961662, 0.35979, 0.594772, 0.967978,    0.121171}, {{1, 3}, {2, 2}, {0, 2}, {0, 1}, {2, 0}, {2, 1}, {3,     2}, {3, 2}}, 0.00253023,   0.551966}, {-140.552, -141.938, -147.171}}, {{{0.0541627, 0.23456,    0.954599, 0.2793, 0.774889, 0.0596392, 0.100017, 0.990815,    0.736931, 0.128057, 0.034801, 0.309314, 0.72363, 0.0391666,    0.879088, 0.132254, 0.436852, 0.0775044, 0.519298, 0.537482,    0.468875, 0.956333, 0.516768, 0.985516},   0.414712, {0.721773, 0.562169, 0.706216, 0.639823, 0.662134,    0.462153, 0.715401, 0.902893, 0.534077, 0.427352, 0.406087,    0.179262, 0.494911, 0.548263, 0.273833, 0.74241, 0.417406,    0.0289648, 0.736351, 0.273535, 0.461073, 0.512197, 0.750835,    0.858823, 0.7393, 0.950027, 0.0446187, 0.219, 0.0771658,    0.487875}, {0.329217, 0.316108, 0.543089, 0.0605234, 0.92313,    0.136845, 0.048178, 0.51226, 0.649297, 0.394435, 0.630772,    0.483295, 0.912946, 0.1209, 0.169699, 0.971099, 0.162111,    0.262077, 0.430399, 0.0210712, 0.117492, 0.0430763, 0.353233,    0.533196, 0.788275, 0.726969, 0.810145, 0.472673, 0.865145,    0.590123}, {0.761967, 0.960413, 0.215848, 0.195688,    0.131195}, {{3, 4}, {3, 1}, {1, 2}, {0, 4}, {2, 4}, {0, 2}, {3,     4}, {0, 4}}, 0.477117,   0.302902}, {-91.5096, -90.2378, -110.41}}, {{{0.0747881, 0.961496,    0.506019, 0.140792, 0.812712, 0.531097, 0.484947, 0.0232993,    0.769635, 0.177863, 0.951751, 0.235024, 0.0426665, 0.367719,    0.479078, 0.369879, 0.452543, 0.605752, 0.518666, 0.154031,    0.256855, 0.474557, 0.0415485, 0.851129},   0.182067, {0.51306, 0.53553, 0.710337, 0.369355, 0.981964,    0.0505825, 0.687038, 0.59972, 0.8041, 0.0988313, 0.452013,    0.557054, 0.436382, 0.619753, 0.0821339, 0.104511, 0.83063,    0.101087, 0.928103, 0.847656, 0.356073, 0.0595386, 0.0769741,    0.665589, 0.843013, 0.524009, 0.366637, 0.296233, 0.861049,    0.473426}, {0.679599, 0.696513, 0.0569491, 0.374595, 0.227586,    0.13946, 0.620568, 0.754842, 0.145452, 0.0349489, 0.789938,    0.653755, 0.217349, 0.187293, 0.433864, 0.594216, 0.140375,    0.521705, 0.590851, 0.0702075, 0.773738, 0.225471, 0.729802,    0.596781, 0.0941388, 0.528958, 0.672853, 0.222187, 0.866553,    0.389498}, {0.0522853, 0.467345, 0.721101, 0.35455,    0.262348}, {{1, 0}, {2, 0}, {3, 1}, {0, 2}, {3, 2}, {0, 2}, {3,     1}, {1, 0}}, 0.81359,   0.503752}, {-52.3431, -45.2335, -66.0531}}, {{{0.167256, 0.828484,    0.219374, 0.363377, 0.645552, 0.237632, 0.149166, 0.589639,    0.420081, 0.50783, 0.552385, 0.4955, 0.891123, 0.834977, 0.330198,     0.628947, 0.501624, 0.782692, 0.862854, 0.907846, 0.147074,    0.520344, 0.0492637, 0.404094},   0.979818, {0.691861, 0.82989, 0.0407175, 0.334266, 0.454229,    0.680724, 0.451079, 0.914186, 0.946398, 0.128339, 0.955578,    0.0230635, 0.111421, 0.798141, 0.326631, 0.521439, 0.328729,    0.935287, 0.418785, 0.374365, 0.808385, 0.886023, 0.0146907,    0.394547, 0.116524, 0.0561335, 0.973973, 0.0602803, 0.662296,    0.37541}, {0.522895, 0.146094, 0.715897, 0.247071, 0.567316,    0.123031, 0.604476, 0.44893, 0.240685, 0.601591, 0.275747,    0.513643, 0.8219, 0.227226, 0.467362, 0.627619, 0.807209, 0.83268,     0.350838, 0.571486, 0.833236, 0.772399, 0.688542, 0.196076,    0.310341, 0.626305, 0.972645, 0.949005, 0.743025,    0.503274}, {0.368168, 0.500075, 0.50234, 0.901683,    0.0924215}, {{0, 1}, {2, 3}, {1, 1}, {0, 4}, {3, 1}, {0, 3}, {3,     0}, {2, 4}}, 0.986432,   0.680441}, {-157.609, -158.388, -160.934}}, {{{0.674456, 0.625059,    0.358813, 0.873232, 0.841777, 0.274222, 0.787327, 0.0399958,    0.0693775, 0.58568, 0.591251, 0.729655, 0.443072, 0.613035,    0.642245, 0.986629, 0.939798, 0.244866, 0.14217, 0.484289,    0.0381154, 0.152445, 0.155738, 0.803848},   0.363659, {0.527386, 0.796925, 0.930616, 0.521882, 0.253164,    0.00959802, 0.890621, 0.452505, 0.667484, 0.418347, 0.160966,    0.00943206, 0.0544494, 0.776102, 0.174337, 0.0696338, 0.809583,    0.633932, 0.690048, 0.0315185, 0.657138, 0.478194, 0.8862,    0.66786, 0.129752, 0.681269, 0.955583, 0.145978, 0.876589,    0.671671}, {0.0649627, 0.693473, 0.209104, 0.253324, 0.903997,    0.684041, 0.154655, 0.477222, 0.72966, 0.614407, 0.345072,    0.84329, 0.0396116, 0.582889, 0.687934, 0.365096, 0.153412,    0.915029, 0.558182, 0.683826, 0.197828, 0.769052, 0.681593,    0.0121552, 0.132866, 0.0755786, 0.472489, 0.758831, 0.228869,    0.391538}, {0.317834, 0.281609, 0.499209, 0.777131,    0.972762}, {{2, 2}, {1, 1}, {0, 3}, {3, 0}, {3, 3}, {0, 2}, {3,     2}, {0, 1}}, 0.438319,   0.459598}, {-97.997, -94.726, -114.002}}, {{{0.194242, 0.284828,    0.0732235, 0.306186, 0.279213, 0.726646, 0.389397, 0.108358,    0.510161, 0.0450534, 0.377242, 0.975492, 0.434583, 0.572565,    0.618411, 0.746623, 0.043045, 0.254731, 0.336801, 0.247414,    0.265914, 0.281969, 0.898482, 0.787816},   0.0716724, {0.997141, 0.825258, 0.48163, 0.79246, 0.270495,    0.435861, 0.373272, 0.282298, 0.225441, 0.0586196, 0.39778,    0.847716, 0.652877, 0.440209, 0.651156, 0.804671, 0.398146,    0.103408, 0.403742, 0.538756, 0.116177, 0.204926, 0.615926,    0.467084, 0.119036, 0.379667, 0.134296, 0.674624, 0.848541,    0.943806}, {0.761024, 0.392326, 0.623099, 0.885186, 0.363244,    0.54461, 0.970223, 0.444977, 0.712088, 0.73994, 0.572077, 0.34157,     0.308345, 0.201183, 0.4559, 0.136644, 0.692419, 0.7341, 0.336865,     0.756977, 0.558123, 0.0594755, 0.488324, 0.813171, 0.797099,    0.66715, 0.865225, 0.927984, 0.433855, 0.122539}, {0.895002,    0.483007, 0.721768, 0.382599,    0.322925}, {{2, 0}, {1, 3}, {3, 4}, {0, 0}, {1, 1}, {1, 0}, {0,     0}, {2, 1}}, 0.141437,   0.413422}, {-66.8663, -59.1249, -89.1991}}, {{{0.181416, 0.867025,    0.00479349, 0.721003, 0.447316, 0.53016, 0.247817, 0.16288,    0.387841, 0.0418362, 0.434646, 0.365781, 0.720691, 0.176612,    0.506662, 0.931926, 0.598152, 0.28161, 0.0236552, 0.210159,    0.215553, 0.958685, 0.882218, 0.796736},   0.0341366, {0.09166, 0.877424, 0.0757327, 0.58682, 0.5615,    0.629607, 0.912852, 0.198979, 0.519664, 0.194961, 0.547071,    0.478288, 0.343052, 0.688299, 0.615145, 0.880136, 0.0614424,    0.664644, 0.404986, 0.664584, 0.102758, 0.782426, 0.60825,    0.630447, 0.0110976, 0.905002, 0.532518, 0.0436267, 0.449598,    0.275394}, {0.619665, 0.844647, 0.929934, 0.0804332, 0.0725944,    0.366359, 0.586882, 0.392134, 0.45745, 0.486223, 0.52544, 0.72749,     0.0524631, 0.821639, 0.422682, 0.945065, 0.444213, 0.191192,    0.411584, 0.040063, 0.911695, 0.147565, 0.961987, 0.764669,    0.29203, 0.302918, 0.0320527, 0.684236, 0.219435,    0.936559}, {0.445171, 0.292101, 0.761986, 0.450336,    0.919731}, {{3, 0}, {1, 1}, {3, 2}, {2, 1}, {3, 0}, {2, 4}, {0,     2}, {3, 1}}, 0.564611,   0.709523}, {-73.461, -63.3486, -90.7548}}, {{{0.628697, 0.497049,    0.619546, 0.26531, 0.437505, 0.0854648, 0.579483, 0.353615,    0.289939, 0.123478, 0.814815, 0.0615849, 0.987021, 0.0914255,    0.130579, 0.842149, 0.050462, 0.646255, 0.838478, 0.0801636,    0.600126, 0.726524, 0.273867, 0.370641},   0.971429, {0.229474, 0.65432, 0.105331, 0.533924, 0.14401,    0.0748371, 0.751716, 0.243984, 0.0205314, 0.260023, 0.690131,    0.256963, 0.929106, 0.129444, 0.847982, 0.206501, 0.282851,    0.290966, 0.767818, 0.606376, 0.556328, 0.0170993, 0.397178,    0.634947, 0.326853, 0.362779, 0.291847, 0.101023, 0.182844,    0.287942}, {0.54013, 0.857039, 0.162312, 0.0279191, 0.849999,    0.600076, 0.233206, 0.898475, 0.0020168, 0.393575, 0.950355,    0.607509, 0.234198, 0.787199, 0.394028, 0.59041, 0.837021,    0.152252, 0.0671746, 0.227631, 0.545174, 0.051229, 0.884331,    0.93969, 0.00504411, 0.19419, 0.722019, 0.91177, 0.155045,    0.594114}, {0.488813, 0.0132949, 0.153029, 0.200539,    0.538457}, {{2, 1}, {0, 0}, {3, 3}, {3, 2}, {1, 1}, {0, 1}, {3,     0}, {0, 3}}, 0.405785,   0.91883}, {-84.8229, -85.7359, -86.8704}}, {{{0.41334, 0.14443,    0.815375, 0.0818092, 0.261088, 0.0772551, 0.587744, 0.536635,    0.209859, 0.192924, 0.648055, 0.531591, 0.0156687, 0.470905,    0.736284, 0.376545, 0.421555, 0.982093, 0.722989, 0.223517,    0.221015, 0.443635, 0.317204, 0.304687},   0.807675, {0.299206, 0.501828, 0.222878, 0.546588, 0.22195,    0.914084, 0.686243, 0.336729, 0.0290264, 0.26603, 0.154652,    0.32106, 0.558121, 0.529746, 0.778106, 0.899506, 0.576029,    0.806756, 0.554589, 0.67849, 0.132393, 0.489553, 0.249903,    0.870815, 0.833188, 0.987724, 0.027025, 0.324227, 0.611237,    0.0736399}, {0.340782, 0.987498, 0.582211, 0.80761, 0.18613,    0.666437, 0.0240898, 0.277865, 0.408024, 0.766932, 0.448061,    0.471108, 0.853435, 0.0884414, 0.315668, 0.981556, 0.603532,    0.217627, 0.48248, 0.993832, 0.576507, 0.8934, 0.871243, 0.920192,     0.235725, 0.905902, 0.289032, 0.112582, 0.0495941,    0.239465}, {0.264942, 0.834717, 0.64157, 0.472533,    0.816881}, {{3, 3}, {2, 4}, {0, 3}, {0, 2}, {3, 3}, {0, 4}, {2,     3}, {1, 3}}, 0.363608,   0.788136}, {-142.602, -143.284, -147.329}}};

  for (unsigned int i = 0; i < sizeof (data) / sizeof (data[0]); ++i)
    {
      NormalDistribution prior_logbeta = 
        normal_distribution (data[i].inputs.logbetamean, 
                             data[i].inputs.logbetastddev);
      float hq = 0;

      for (unsigned int j = 0; j < 5; ++j)
        {
          hq -= data[i].inputs.pz[j] * log (data[i].inputs.pz[j]);
        }

      float dlogbeta;
      float ddlogbeta;

      float q = qfunc (data[i].inputs.loga,
                       6,
                       data[i].inputs.logbeta,
                       &dlogbeta,
                       &ddlogbeta,
                       data[i].inputs.c,
                       5,
                       data[i].inputs.d,
                       data[i].inputs.pz,
                       data[i].inputs.ratings,
                       8,
                       &prior_logbeta.base,
                       hq);

      assert (fabs (q - data[i].desired_output.q) <=
              1e-4 * (1 + fabs (q) + fabs (data[i].desired_output.q)) ||
              (fprintf (stderr, "q: %g ?= %g\n", q, data[i].desired_output.q),
               0));

      assert (fabs (dlogbeta - data[i].desired_output.dlogbeta) <=
              1e-4 * (1 + fabs (dlogbeta) + fabs (data[i].desired_output.dlogbeta)) ||
              (fprintf (stderr, "dlogbeta: %g ?= %g\n", dlogbeta, data[i].desired_output.dlogbeta),
               0));

      assert (fabs (ddlogbeta - data[i].desired_output.ddlogbeta) <=
              1e-4 * (1 + fabs (ddlogbeta) + fabs (data[i].desired_output.ddlogbeta)) ||
              (fprintf (stderr, "ddlogbeta: %g ?= %g\n", ddlogbeta, data[i].desired_output.ddlogbeta),
               0));

    }
}

typedef struct _DQFuncTestDatum DQFuncTestDatum;
struct _DQFuncTestDatum
{ 
  struct
    {
      float    loga[6 * 4];
      float    logbeta;
      float    c[6 * 5];
      float    d[6 * 5];
      float    pz[5];
      Rating    ratings[8];
      float    logbetamean;
      float    logbetastddev;
    }                   inputs;

  struct
    {
      float     dloga[6 * 4];
      float     dc[6 * 5];
      float     dd[6 * 5];
    }                   desired_output;
};

static void
test_dqfunc (void)
{
  DQFuncTestDatum data[] = 
    {{{{0.384091, 0.501213, 0.382053, 0.184604, 0.166465, 0.0187326,    0.388221, 0.608097, 0.273065, 0.14749, 0.468029, 0.372372,    0.367163, 0.858458, 0.355448, 0.322778, 0.127699, 0.593516,    0.520731, 0.681208, 0.655166, 0.776635, 0.157122, 0.893073},   0.271074, {0.275422, 0.77507, 0.708469, 0.10461, 0.25669, 0.386849,     0.100372, 0.831544, 0.1092, 0.91882, 0.728, 0.464381, 0.250742,    0.563372, 0.405222, 0.336682, 0.657226, 0.0426414, 0.724013,    0.681516, 0.880591, 0.885519, 0.830941, 0.410442, 0.605169,    0.110449, 0.122472, 0.305832, 0.34848, 0.7236}, {0.0220999,    0.474288, 0.23928, 0.80478, 0.2941, 0.00990689, 0.988537,    0.241408, 0.888878, 0.673225, 0.331311, 0.198767, 0.164865,    0.991708, 0.45072, 0.313248, 0.333924, 0.581266, 0.84555,    0.202799, 0.211452, 0.275434, 0.497071, 0.479199, 0.189352,    0.801146, 0.257791, 0.674418, 0.895252, 0.791239}, {0.269254,    0.43301, 0.00637369, 0.118014,    0.937943}, {{0, 0}, {3, 0}, {2, 4}, {3, 4}, {2, 4}, {3, 2}, {1,     0}, {1, 2}}, 0.234243,   0.841509}, {{-0.603801, -0.770093, -0.822182, -0.776951,-0.697395, -0.833938, -1.54503, -2.20262, -1.57915, -1.8649,-2.46858, -2.51175, -0.945241, -1.56565, -1.08138, -0.837584,-0.806981, -1.22105, -2.42674, -3.18194, -3.18935, -4.34842,-2.32466, -5.27167}, {-0.53453, -1.30905, -0.0139583, -0.348048,-1.67671, -0.870191, -1.93384, -0.0219938, -0.512149, -1.96849,-0.587946, -1.52951, -0.0174297, -0.409552, -1.96, -0.616865,-1.55058, -0.015698, -0.414729, -2.20174, -0.447541, -1.16801,-0.0116192, -0.310833, -1.74061, -0.967576, -2.3745, -0.0261987,-0.637508, -3.01971}, {-2.02276, 0.0388557, -1.59717,    0.0186884, -1.20935, -2.7655, 0.0657392, -2.21496,    0.0253211, -1.40823, -2.11681, 0.0472402, -1.76377,    0.0190213, -1.30549, -2.38709, 0.0462783, -2.00341,    0.0185907, -1.34779, -2.06576, 0.045218, -1.73178,    0.0203013, -1.08475, -2.3417, 0.049309, -2.10176,    0.0182095, -1.22706}}}, {{{0.126306, 0.487223, 0.920995, 0.507585,     0.54504, 0.641673, 0.718196, 0.296133, 0.269607, 0.144602,    0.238998, 0.106781, 0.468461, 0.886811, 0.56458, 0.211528,    0.677222, 0.617557, 0.13157, 0.205155, 0.559208, 0.679614,    0.897327, 0.363646},   0.432902, {0.192391, 0.976332, 0.856061, 0.887862, 0.550718,    0.258135, 0.559929, 0.618256, 0.406116, 0.0191374, 0.453148,    0.149795, 0.519306, 0.454558, 0.24162, 0.472572, 0.901749,    0.322988, 0.0364648, 0.913364, 0.222135, 0.425661, 0.672819,    0.480462, 0.0297444, 0.44933, 0.816758, 0.5926, 0.479026,    0.191195}, {0.256829, 0.974344, 0.0729099, 0.172057, 0.803681,    0.82455, 0.553604, 0.7175, 0.562061, 0.351977, 0.651855, 0.394511,     0.525597, 0.438613, 0.42972, 0.96885, 0.852778, 0.958152,    0.399975, 0.51952, 0.0360203, 0.365552, 0.920949, 0.328326,    0.779191, 0.391208, 0.848039, 0.156269, 0.97551,    0.566658}, {0.294435, 0.438769, 0.413449, 0.214681,    0.64258}, {{2, 0}, {0, 4}, {3, 3}, {0, 4}, {2, 1}, {3, 3}, {3,     0}, {0, 4}}, 0.0442575,   0.887852}, {{-3.73333, -3.38678, -5.10793, -3.89035, -4.67106,-4.98191, 0, 0, 0, 0, 0,    0, -3.57549, -4.51694, -3.00522, -3.16584, -2.57266, -3.55262,-3.11541, -3.62335, -4.64372, -7.03446, -5.3268, -5.10537},{-0.889872, -1.37356, -1.62789, -0.694535, -1.49344, -1.05362,-1.91563, -2.20529, -0.928621, -2.29483, -1.35656, -2.41998,-2.54012, -1.03561, -2.12427, -1.13994, -2.17413, -2.29085,-0.878235, -2.26633, -1.36421, -2.27341, -2.42792, -0.894746,-2.2103, -1.3409, -2.15073, -2.38876, -0.923438, -2.19863},{-2.11479, -1.02071,    0.0180409, -1.72136, -2.08069, -2.14947, -1.23124,    0.0180802, -1.47435, -2.52995, -1.99509, -0.959162,    0.0243303, -2.08401, -3.61101, -2.30658, -0.751833,    0.0264954, -3.04543, -2.59603, -2.58235, -1.00879,    0.0223971, -2.91335, -2.63644, -2.12445, -1.01684,    0.0213033, -1.92599, -3.20746}}}, {{{0.776067, 0.21286, 0.0754073,     0.0350745, 0.817916, 0.812885, 0.555887, 0.999054, 0.452364,    0.891936, 0.227561, 0.219863, 0.0611562, 0.043897, 0.0712927,    0.244353, 0.494498, 0.749462, 0.632524, 0.830904, 0.279817,    0.106882, 0.588266, 0.943051},   0.50375, {0.894021, 0.512859, 0.907977, 0.685834, 0.0811364,    0.956972, 0.908923, 0.23347, 0.1892, 0.729411, 0.68906, 0.172314,    0.145303, 0.658118, 0.444707, 0.677816, 0.395841, 0.0255942,    0.613804, 0.397999, 0.28896, 0.437328, 0.670752, 0.894249,    0.394938, 0.924469, 0.762775, 0.208414, 0.313802,    0.967497}, {0.853853, 0.974944, 0.124601, 0.238086, 0.164793,    0.80263, 0.979298, 0.579969, 0.720086, 0.124814, 0.583457,    0.554374, 0.106282, 0.726816, 0.294497, 0.117046, 0.43553,    0.832567, 0.899559, 0.192577, 0.672754, 0.624152, 0.585757,    0.22508, 0.818901, 0.649208, 0.461156, 0.986994, 0.654109,    0.846578}, {0.481858, 0.407025, 0.934023, 0.721764,    0.898401}, {{3, 1}, {1, 4}, {2, 0}, {0, 2}, {3, 4}, {1, 2}, {0,     1}, {1, 4}}, 0.852651,   0.827741}, {{-8.23515, -5.24287, -3.24855, -3.68453, -8.60956,-9.66372, -7.02987, -11.1046, -5.7725, -10.2455, -7.26595, -7.66137,-2.44806, -2.21339, -1.85927, -1.5112, -3.53286, -4.29853, -7.71854,-8.27535, -4.14869, -3.11367, -7.58097, -9.76808}, {-2.47572,-1.40836, -4.1332, -4.08994, -3.5434, -2.90847, -1.87729, -4.46752,-4.71899, -3.72289, -1.64987, -1.16133, -2.84809, -2.80239, -2.0573,-2.20052, -1.66746, -2.95529, -3.57102, -2.67632, -2.65499, -1.80269,-4.37121, -4.5101, -3.67733, -3.09313, -2.20518, -5.04961, -5.3128,-4.30488}, {-1.32424, -5.44488, -4.00097,    0.0277601, -6.66059, -1.23193, -4.37688, -4.48987,    0.0238735, -7.91198, -1.18378, -2.88882, -2.75676,    0.015497, -4.35785, -1.37422, -2.46897, -3.6274,    0.0172733, -5.75304, -2.13321, -5.36774, -3.70074,    0.0281406, -4.87599, -2.63865, -6.32681, -4.19047,    0.0311972, -5.15588}}}, {{{0.994949, 0.603904, 0.735604, 0.392212,     0.162382, 0.704345, 0.543027, 0.719458, 0.538229, 0.118588,    0.317947, 0.900556, 0.889021, 0.657432, 0.330954, 0.246447,    0.0424428, 0.175574, 0.923928, 0.312424, 0.320679, 0.277173,    0.0712776, 0.484683},   0.32573, {0.673269, 0.335673, 0.0924713, 0.163349, 0.968924,    0.792646, 0.373014, 0.625119, 0.850337, 0.474699, 0.472458,    0.736098, 0.192905, 0.143745, 0.22601, 0.693656, 0.0173308,    0.219817, 0.913586, 0.372977, 0.740158, 0.148539, 0.428903,    0.0472466, 0.0668887, 0.812866, 0.336432, 0.883898, 0.0979646,    0.0202202}, {0.963418, 0.258779, 0.247628, 0.545521, 0.49096,    0.522681, 0.0547232, 0.401776, 0.26495, 0.829025, 0.0373925,    0.181959, 0.351364, 0.456048, 0.297235, 0.0334201, 0.922461,    0.408802, 0.230346, 0.220554, 0.586029, 0.524903, 0.132381,    0.200334, 0.622611, 0.266125, 0.884753, 0.654812, 0.131651,    0.743444}, {0.83003, 0.253036, 0.866701, 0.914419,    0.792638}, {{0, 2}, {1, 1}, {1, 3}, {1, 1}, {3, 2}, {3, 2}, {3,     0}, {3, 1}}, 0.0710767,   0.515337}, {{-3.29259, -2.70879, -2.33792, -2.1145, -1.05385,-2.7534, -7.27758, -8.0553, -5.89909, -6.34079, -5.62239, -12.9909, 0,     0, 0, 0, 0,    0, -13.552, -7.77658, -5.55945, -7.82696, -4.69079, -9.27258},{-3.71475, -0.924233, -2.78745, -4.40174, -4.32011, -2.77462,-0.591683, -1.95297, -2.83092, -2.9446, -2.76723, -0.564491, -1.7984,-2.7379, -2.82626, -2.64558, -0.462322, -1.81465, -2.82334, -2.70577,-2.11486, -0.378531, -1.73103, -2.25379, -2.26672, -4.49472,-0.728846, -3.26774, -4.64021, -4.55161}, {-2.10992, -6.64984,-7.5822, -1.4796, 0.0923366, -1.31244, -7.13065, -4.79771, -1.93957,    0.0860571, -1.00814, -4.6403, -4.00349, -1.32938,    0.0615391, -1.16216, -4.26361, -4.16574, -0.889744,    0.0645386, -0.751502, -3.88223, -2.63937, -1.11809,    0.0466907, -1.28006, -7.3437, -4.32049, -2.25879,    0.0863981}}}, {{{0.458371, 0.495403, 0.0376565, 0.592877,    0.0495695, 0.265057, 0.817103, 0.00684773, 0.524666, 0.132676,    0.616769, 0.384237, 0.258541, 0.247922, 0.961956, 0.252586,    0.515097, 0.417892, 0.70892, 0.385885, 0.600678, 0.625255,    0.637844, 0.870548},   0.142307, {0.129852, 0.600187, 0.277672, 0.0927379, 0.864795,    0.783085, 0.270824, 0.568072, 0.732119, 0.166316, 0.886587,    0.30953, 0.484197, 0.204359, 0.634001, 0.794433, 0.0663041,    0.495439, 0.248116, 0.193755, 0.441049, 0.857595, 0.377567,    0.0514473, 0.311198, 0.257408, 0.099896, 0.958709, 0.446403,    0.474323}, {0.829072, 0.390638, 0.714284, 0.308007, 0.942485,    0.0811072, 0.230087, 0.103648, 0.308484, 0.286674, 0.163783,    0.608209, 0.0603689, 0.0929196, 0.722734, 0.750614, 0.682801,    0.0414723, 0.411536, 0.493206, 0.582905, 0.0827629, 0.965133,    0.0188826, 0.753833, 0.692125, 0.250849, 0.710875, 0.811348,    0.611018}, {0.020762, 0.607227, 0.502864, 0.324344,    0.856979}, {{3, 3}, {1, 1}, {0, 4}, {1, 0}, {0, 3}, {2, 1}, {3,     0}, {0, 2}}, 0.999018,   0.442495}, {{-3.32601, -2.31014, -1.55386, -2.36807, -2.0545,-2.7167, -4.02674, -1.09644, -2.37552, -1.74982, -2.42854, -2.32924,-0.786784, -0.643143, -1.90407, -0.835168, -0.633143, -0.866398,-4.02449, -1.8271, -2.3809, -2.90379, -2.85775, -4.87756},{-0.0551446, -1.89198, -1.84455, -0.984458, -3.02538, -0.0389442,-1.09004, -1.03418, -0.490575, -1.67257, -0.047079, -1.02398,-1.4321, -0.747236, -2.30058, -0.0500237, -1.5535, -1.53259,-0.732697, -2.43282, -0.038056, -1.31429, -1.31355, -0.720065,-2.22016, -0.053106, -1.81714, -1.71522, -0.773832, -2.87968},{-2.77234, -1.61182, -0.716875, -1.98726, -0.526898, -1.35812,-0.914328, -0.618749, -1.38906, -0.608862, -2.11489, -1.98647,-0.389319, -1.44243, -0.33037, -1.50966, -0.897694, -0.609818,-1.56693, -0.573587, -2.23556, -1.36246, -0.400685, -1.48668,-0.375113, -2.37103, -1.41577, -0.477356, -1.89701, -0.468067}}},{{{0.231424, 0.134245, 0.248405, 0.759693, 0.189952, 0.722708,    0.755199, 0.176788, 0.107189, 0.757575, 0.736316, 0.422955,    0.415064, 0.506726, 0.0254409, 0.611606, 0.804046, 0.485964,    0.418214, 0.108743, 0.479702, 0.628985, 0.419195, 0.666248},   0.248277, {0.49474, 0.170791, 0.906555, 0.0583251, 0.772032,    0.415592, 0.729767, 0.951136, 0.0144569, 0.679276, 0.306813,    0.536072, 0.507731, 0.653835, 0.695206, 0.732026, 0.0217677,    0.235622, 0.586463, 0.252325, 0.392783, 0.816426, 0.920215,    0.00404737, 0.898043, 0.645635, 0.0136602, 0.945722, 0.126011,    0.230043}, {0.283893, 0.994587, 0.111554, 0.550767, 0.97708,    0.458515, 0.603822, 0.896932, 0.281874, 0.726488, 0.582055,    0.66131, 0.695411, 0.474164, 0.189272, 0.844884, 0.775196,    0.470116, 0.291229, 0.199249, 0.761536, 0.524394, 0.165219,    0.969206, 0.477643, 0.529808, 0.053665, 0.418439, 0.500562,    0.071293}, {0.449843, 0.521507, 0.218688, 0.344805,    0.867788}, {{2, 4}, {3, 3}, {1, 1}, {0, 1}, {2, 1}, {0, 0}, {0,     3}, {1, 0}}, 0.860196,   0.523277}, {{-3.73091, -3.06463, -3.73817, -5.42787, -4.31236,-4.36396, -4.27726, -2.24174, -2.2721, -4.07391, -4.54369, -2.01895,-3.13573, -2.90365, -1.58315, -2.74181, -3.67193, -1.63656, -1.55665,-0.983352, -1.53615, -1.29632, -2.246, -1.65196}, {-1.56784,-1.17635, -0.983946, -1.14534, -3.32482, -1.10715, -0.911694,-0.714839, -0.831938, -2.26906, -1.01883, -0.933883, -0.686731,-0.701194, -2.45904, -1.66784, -1.54261, -1.19979, -1.39818,-4.29148, -1.57054, -1.47928, -1.05292, -1.17747, -3.52757, -1.20262,-1.33722, -0.858805, -0.828949, -3.03442}, {-2.05989, -3.0811,    0.110622, -1.85273, -0.586809, -1.50884, -2.40835,    0.0986848, -1.5863, -0.743656, -1.56292, -2.11445,    0.102407, -1.91335, -0.418104, -2.14554, -3.431,    0.144974, -2.20586, -0.71362, -2.2897, -3.5354,    0.136369, -2.03547, -1.01641, -1.78182, -2.85865,    0.117123, -2.28814, -0.621831}}}, {{{0.870641, 0.678516, 0.015312,     0.748081, 0.400524, 0.387287, 0.816063, 0.986545, 0.87613,    0.222068, 0.846857, 0.508903, 0.346323, 0.168403, 0.428419,    0.00834061, 0.27503, 0.71856, 0.906912, 0.789653, 0.930225,    0.850772, 0.0467156, 0.266376},   0.0595844, {0.172256, 0.0314036, 0.518295, 0.65906, 0.78497,    0.21534, 0.53175, 0.78293, 0.562901, 0.368483, 0.0228473,    0.436607, 0.394498, 0.940065, 0.0145066, 0.161577, 0.675938,    0.0331526, 0.224854, 0.231352, 0.825165, 0.986437, 0.958478,    0.171767, 0.652909, 0.955033, 0.440183, 0.512707, 0.867939,    0.739693}, {0.908433, 0.729778, 0.305038, 0.37121, 0.885585,    0.293171, 0.91054, 0.431145, 0.871079, 0.131594, 0.234602,    0.397993, 0.646225, 0.900243, 0.409437, 0.411556, 0.687747,    0.728475, 0.756528, 0.456522, 0.247565, 0.215768, 0.888588,    0.716829, 0.339132, 0.485991, 0.58355, 0.345619, 0.453547,    0.19282}, {0.67301, 0.914474, 0.582468, 0.0612256,    0.438408}, {{0, 1}, {2, 4}, {3, 2}, {0, 4}, {0, 3}, {3, 0}, {1,     0}, {0, 4}}, 0.516482,   0.936243}, {{-7.58624, -6.38677, -2.8996, -6.28321, -5.78431,-4.75689, -2.00711, -1.85227, -1.35444, -0.823879, -1.85109,-1.29524, -1.10817, -0.650099, -0.95847, -0.656978, -1.1225,-1.30381, -3.55871, -3.02874, -3.20506, -3.51859, -2.10245,-2.02914}, {-2.41208, -4.13188, -2.73974, -0.289081, -1.41833,-1.75558, -2.88012, -1.90554, -0.195787, -1.21975, -1.33032, -2.6229,-1.40276, -0.172744, -0.983233, -2.04586, -3.09932, -1.94182,-0.208495, -1.17789, -1.29298, -2.19103, -1.39942, -0.140823,-0.751628, -1.30128, -2.14487, -1.43535, -0.147549, -0.750218},{-2.13971, -0.987866, -1.03168, -1.33141, -2.80864, -2.57358,-0.810086, -1.0285, -1.24551, -2.86297, -2.25436, -0.318321, -1.0758,-0.518719, -1.72595, -1.62772, -0.68324, -1.10799, -1.20274,-2.61179, -2.11902, -0.756959, -0.602859, -1.19689, -3.06395,-1.50012, -0.712565, -0.694802, -1.0123, -3.03581}}}, {{{0.160983,    0.0289716, 0.104926, 0.248496, 0.432508, 0.272444, 0.648404,    0.00093133, 0.216739, 0.383856, 0.931574, 0.661799, 0.730749,    0.800306, 0.585955, 0.208253, 0.537929, 0.127295, 0.671481,    0.625785, 0.476703, 0.688887, 0.154999, 0.689542},   0.31572, {0.659915, 0.0500732, 0.441046, 0.883213, 0.387472,    0.401669, 0.440114, 0.666473, 0.00361592, 0.470095, 0.778315,    0.935725, 0.20331, 0.88414, 0.570062, 0.397796, 0.0760151,    0.212659, 0.944278, 0.921092, 0.387128, 0.0576604, 0.254736,    0.605372, 0.727213, 0.0075872, 0.813691, 0.722159, 0.339741,    0.605918}, {0.373576, 0.055686, 0.336125, 0.135823, 0.595261,    0.119961, 0.132815, 0.251682, 0.0251991, 0.722166, 0.0567996,    0.0390229, 0.0809214, 0.801074, 0.669672, 0.981363, 0.826185,    0.195702, 0.942459, 0.973775, 0.0124947, 0.473542, 0.602718,    0.367858, 0.638918, 0.417856, 0.266593, 0.232035, 0.0436569,    0.297895}, {0.133778, 0.980353, 0.0184578, 0.575729,    0.0769787}, {{0, 0}, {0, 0}, {1, 2}, {2, 0}, {0, 0}, {1, 2}, {3,     2}, {0, 4}}, 0.94133,   0.937536}, {{-3.12145, -2.26272, -3.38126, -4.91634, -3.0187,-4.0016, -2.74829, -1.25612, -1.94834, -1.90575, -4.09842, -2.92896,-1.40722, -1.15581, -1.28522, -1.26155, -0.791001, -0.956033,-1.41904, -1.18672, -1.28117, -1.31147, -0.94995, -1.5242},{-0.261115, -3.56725, -0.0354928, -2.18112, -0.258045, -0.175588,-2.58297, -0.0287259, -1.57787, -0.179608, -0.161844, -2.35518,-0.0261031, -1.46689, -0.161758, -0.214322, -3.75671, -0.0457553,-2.31097, -0.26267, -0.334887, -3.86104, -0.0313545, -2.36848,-0.271091, -0.240155, -3.31683, -0.0324633, -2.02414, -0.23998},{-2.76054, 0.0603173, -3.08662, 0.074672, -0.582083, -2.48663,    0.0335002, -1.90289, 0.0792159, -0.472537, -3.50907,    0.0541404, -2.94441, 0.109292, -0.753457, -2.60444,    0.0592967, -2.68473, 0.0733885, -0.64621, -2.93046,    0.0636839, -3.0919, 0.0900617, -0.70326, -2.97456,    0.0453127, -3.58003, 0.118731, -0.742649}}}, {{{0.774655,    0.407307, 0.959967, 0.111351, 0.578954, 0.464848, 0.986192,    0.0988564, 0.105411, 0.86213, 0.618334, 0.459938, 0.687555,    0.595537, 0.386299, 0.416281, 0.38966, 0.461759, 0.405946,    0.397823, 0.813931, 0.38478, 0.464617, 0.460287},   0.0392754, {0.977473, 0.50465, 0.348936, 0.460322, 0.512625,    0.518458, 0.25008, 0.35491, 0.650495, 0.900124, 0.790142,    0.667356, 0.0549581, 0.513825, 0.37386, 0.277696, 0.593199,    0.107878, 0.976037, 0.463765, 0.20842, 0.643262, 0.51575, 0.42449,     0.230947, 0.138612, 0.166814, 0.964168, 0.718322,    0.620154}, {0.916734, 0.609257, 0.0678269, 0.72003, 0.126592,    0.941902, 0.0128689, 0.206205, 0.752732, 0.664206, 0.419669,    0.0983266, 0.776695, 0.200441, 0.21125, 0.455065, 0.260946,    0.775951, 0.980303, 0.316453, 0.0941321, 0.811783, 0.261981,    0.696299, 0.177398, 0.202526, 0.194154, 0.976269, 0.0508057,    0.260624}, {0.181285, 0.770064, 0.298074, 0.596418,    0.761616}, {{2, 1}, {0, 0}, {1, 1}, {2, 0}, {1, 0}, {2, 2}, {1,     2}, {2, 0}}, 0.671738,   0.521378}, {{-2.43398, -1.81295, -2.12076, -1.00442, -1.07366,-1.141, -6.50602, -2.63296, -2.53735, -6.02288, -3.66499, -3.77104,-6.87523, -6.35297, -4.43457, -5.07091, -3.67825, -4.78577, 0, 0, 0,    0, 0, 0}, {-0.328465, -2.65407, -1.10822, -2.87092, -3.62607,-0.156794, -1.86127, -0.669474, -1.79836, -2.29396, -0.192033,-1.69518, -0.553327, -1.63799, -2.08105, -0.313825, -1.94679,-0.628649, -2.06598, -2.60746, -0.270802, -1.34202, -0.578587,-1.6821, -2.12132, -0.268964, -1.66241, -0.504218, -1.70988,-2.1747}, {-5.31407, -2.04328, -2.68219, 0.1331,    0.260769, -3.9822, -1.40734, -1.72565, 0.0946433,    0.165376, -3.9883, -1.02872, -1.47123, 0.0869805,    0.172367, -4.21105, -1.75944, -2.37762, 0.097088,    0.211141, -3.8812, -1.28343, -1.7661, 0.0929089,    0.192054, -3.99299, -1.51045, -1.72831, 0.0934198,    0.178492}}}, {{{0.395977, 0.550366, 0.216673, 0.260433, 0.620026,    0.570063, 0.90022, 0.1663, 0.808243, 0.308082, 0.20392, 0.988902,    0.605717, 0.113928, 0.227651, 0.938097, 0.345092, 0.932642,    0.457586, 0.640023, 0.748674, 0.171026, 0.785849, 0.118645},   0.352697, {0.62066, 0.569176, 0.858212, 0.732671, 0.0505965,    0.668956, 0.691912, 0.924428, 0.742515, 0.465036, 0.703009,    0.318712, 0.628587, 0.237385, 0.764913, 0.973619, 0.695945,    0.779799, 0.12489, 0.224945, 0.524919, 0.99395, 0.0062452,    0.872248, 0.904259, 0.424774, 0.148033, 0.139578, 0.853662,    0.755818}, {0.456121, 0.215149, 0.111148, 0.290782, 0.753112,    0.896438, 0.482561, 0.0533963, 0.988199, 0.922818, 0.786616,    0.273598, 0.863309, 0.697873, 0.261697, 0.279647, 0.857064,    0.825625, 0.357438, 0.854873, 0.709031, 0.686047, 0.503776,    0.0990556, 0.252909, 0.470898, 0.392628, 0.808274, 0.499798,    0.57446}, {0.910067, 0.754878, 0.511599, 0.651642,    0.123451}, {{2, 2}, {0, 0}, {1, 1}, {3, 2}, {3, 2}, {3, 0}, {0,     0}, {1, 1}}, 0.48128,   0.64829}, {{-3.40521, -5.46374, -2.93339, -2.33782, -5.1342,-3.45563, -5.16828, -3.13712, -4.56552, -4.26631, -3.26251, -5.80886,-1.86828, -1.13202, -1.96334, -4.34249, -2.17008, -3.87807, -5.03341,-6.8236, -9.11072, -5.10064, -9.77547, -4.53614}, {-2.44986,-2.13843, -1.50013, -2.77628, -0.52474, -1.82734, -2.70006, -1.62242,-2.88077, -0.543636, -3.39374, -3.24945, -1.65832, -3.69748,-0.698268, -2.99296, -2.43851, -1.1726, -2.88823, -0.545967,-2.73064, -3.3275, -1.69432, -3.51155, -0.66377, -3.4409, -2.72933,-1.70832, -3.52171, -0.665207}, {-3.63891, -4.2576, -4.6025,    0.0411685, 0.0331115, -4.52743, -2.09827, -4.75342, 0.0416128,    0.0337192, -3.09014, -3.58762, -4.60826, 0.0390247,    0.0296986, -2.73861, -2.28609, -4.59907, 0.0369386,    0.0262175, -4.84658, -1.91359, -5.93498, 0.0432429,    0.0354787, -3.15671, -4.17602, -4.0444, 0.0335703, 0.0274223}}}};

  for (unsigned int i = 0; i < sizeof (data) / sizeof (data[0]); ++i)
    {
      float dloga[6 * 4];
      float dc[6 * 5];
      float dd[6 * 5];

      memset (dloga, 0, sizeof (dloga));
      memset (dc, 0, sizeof (dc));
      memset (dd, 0, sizeof (dd));

      dqfunc (dloga,
              dc,
              dd,
              data[i].inputs.loga,
              6,
              data[i].inputs.logbeta,
              data[i].inputs.c,
              5,
              data[i].inputs.d,
              data[i].inputs.pz,
              data[i].inputs.ratings,
              8);

      for (unsigned int j = 0; j < 6 * 4; ++j)
        {
          assert (fabs (dloga[j] - data[i].desired_output.dloga[j]) <=
                  1e-4 * (1 + fabs (dloga[j]) + fabs (data[i].desired_output.dloga[j])) ||
                  (fprintf (stderr, "dloga[%u]: %g ?= %g\n", j, dloga[j], data[i].desired_output.dloga[j]),
                   0));
        }

      for (unsigned int j = 0; j < 6 * 5; ++j)
        {
          assert (fabs (dc[j] - data[i].desired_output.dc[j]) <=
                  1e-4 * (1 + fabs (dc[j]) + fabs (data[i].desired_output.dc[j])) ||
                  (fprintf (stderr, "dc[%u]: %g ?= %g\n", j, dc[j], data[i].desired_output.dc[j]),
                   0));
        }

      for (unsigned int j = 0; j < 6 * 5; ++j)
        {
          assert (fabs (dd[j] - data[i].desired_output.dd[j]) <=
                  2e-4 * (1 + fabs (dd[j]) + fabs (data[i].desired_output.dd[j])) ||
                  (fprintf (stderr, "dd[%u]: %g ?= %g\n", j, dd[j], data[i].desired_output.dd[j]),
                   0));
        }
    }
}

int 
main (void) 
{
  test_qfunc ();
  test_dqfunc ();

  return 0;
}
